package cn.fang2chen.java.distributed.lock.framework;

import java.util.concurrent.TimeUnit;

/**
 * 使用包装器模式。
 * 使用 acquire() 方法轮询  tryAcquire() 方法来实现阻塞锁的功能
 *
 * @author dcmini chen
 * @since 1.0.0
 */
public class PollingTryAcquireRemoteLockSynchronizer extends RemoteLockSyncDecorator{

    /**
     * 被包装的对象
     */
    private final RemoteLockSynchronizer remoteLockSynchronizer;

    /**
     * 轮询的时间间隔
     */
    private long pollingIntervalNano = 0;

    public PollingTryAcquireRemoteLockSynchronizer(RemoteLockSynchronizer remoteLockSynchronizer) {
        this.remoteLockSynchronizer = remoteLockSynchronizer;
    }

    public PollingTryAcquireRemoteLockSynchronizer(RemoteLockSynchronizer remoteLockSynchronizer, long pollingIntervalNano) {
        this.remoteLockSynchronizer = remoteLockSynchronizer;
        this.pollingIntervalNano = pollingIntervalNano;
    }

    @Override
    public RemoteLockSynchronizer remoteLockSynchronizer() {
        return this.remoteLockSynchronizer;
    }

    @Override
    public boolean tryAcquire( RemoteLockParam remoteLockParam, long time, TimeUnit unit) throws InterruptedException {

        long deadLine = System.nanoTime() + unit.toNanos(time);

        for (; ; ) {

            if (Thread.currentThread().isInterrupted()) {
                throw new InterruptedException();
            }

            if (System.nanoTime() >= deadLine) {
                return false;
            }

            if (pollingIntervalNano > 0) {
                try {
                    TimeUnit.NANOSECONDS.sleep(pollingIntervalNano);
                } catch (InterruptedException e) {
                    throw new InterruptedException();
                }
            }

            if (tryAcquire(remoteLockParam)) {
                return true;
            }

        }
    }
}
